package _binary_tree

import common.TreeNode
import org.junit.Assert
import org.junit.Test
import common.printLevelOrder3

/**
 * https://leetcode.cn/problems/maximum-binary-tree-ii/description
 *
 * 题型：二叉树的迭代遍历-双指针法
 * ```
 * 998. 最大二叉树 II
 * 大树 定义：一棵树，并满足：其中每个节点的值都大于其子树中的任何其他值。
 * 给你最大树的根节点 root 和一个整数 val 。
 * 就像 之前的问题 那样，给定的树是利用 Construct(a) 例程从列表 a（root = Construct(a)）递归地构建的：
 * 如果 a 为空，返回 null 。
 * 否则，令 a[i] 作为 a 的最大元素。创建一个值为 a[i] 的根节点 root 。
 * root 的左子树将被构建为 Construct([a[0], a[1], ..., a[i - 1]]) 。
 * root 的右子树将被构建为 Construct([a[i + 1], a[i + 2], ..., a[a.length - 1]]) 。
 * 返回 root 。
 * 请注意，题目没有直接给出 a ，只是给出一个根节点 root = Construct(a) 。
 * 假设 b 是 a 的副本，并在末尾附加值 val。题目数据保证 b 中的值互不相同。
 * 返回 Construct(b) 。
 *
 * 示例 1：
 * 输入：root = [4,1,3,null,null,2], val = 5
 * 输出：[5,4,null,1,3,null,null,2]
 * 解释：a = [1,4,2,3], b = [1,4,2,3,5]

 * 示例 2：
 * 输入：root = [5,2,4,null,1], val = 3
 * 输出：[5,2,4,null,1,null,3]
 * 解释：a = [2,1,5,4], b = [2,1,5,4,3]

 * 示例 3：
 * 输入：root = [5,2,3,null,1], val = 4
 * 输出：[5,2,4,null,1,3]
 * 解释：a = [2,1,5,3], b = [2,1,5,3,4]
 *
 * 提示：
 * 树中节点数目在范围 [1, 100] 内
 * 1 <= Node.val <= 100
 * 树中的所有值 互不相同
 * 1 <= val <= 100
 *
 * ```
 */
class leetcode_998 {
    @Test
    fun test_1() {
        val n1 = TreeNode(1)
        val n2 = TreeNode(2)
        val n3 = TreeNode(3)
        val n4 = TreeNode(4)
        val root = n4
        n4.left = n1
        n4.right = n3

        n3.left = n2

        val actual = insertIntoMaxTree(root, 5)
        val expected = arrayListOf(5, 4, null, 1, 3, null, null, 2)
        Assert.assertEquals(expected.toString(), printLevelOrder3(actual).toString())
    }

    @Test
    fun test_2() {
        val n1 = TreeNode(1)
        val n2 = TreeNode(2)
        val n4 = TreeNode(4)
        val n5 = TreeNode(5)
        val root = n5
        n5.left = n2
        n5.right = n4

        n2.right = n1

        val actual = insertIntoMaxTree(root, 3)
        val expected = arrayListOf(5, 2, 4, null, 1, null, 3)
        Assert.assertEquals(expected.toString(), printLevelOrder3(actual).toString())
    }

    @Test
    fun test_3() {
        val n1 = TreeNode(1)
        val n2 = TreeNode(2)
        val n3 = TreeNode(3)
        val n5 = TreeNode(5)
        val root = n5
        n5.left = n2
        n5.right = n3

        n2.right = n1

        val actual = insertIntoMaxTree(root, 4)
        val expected = arrayListOf(5, 2, 4, null, 1, 3)
        Assert.assertEquals(expected.toString(), printLevelOrder3(actual).toString())
    }

    private fun insertIntoMaxTree(root: TreeNode?, `val`: Int): TreeNode? {
        /**
        题型：二叉树的迭代遍历-双指针法
        思路：
        遍历root，利用双指针法(prev, current),根据条件current.val > val，找到不满足条件的prev
        如果val 是最大值，则pre 为空，那么 val将作为新的根节点，root 作为 它 的左孩子，返回新的根节点
        如果val 不是最大值， 则pre 不为空，那么 prev -> right = 新node, 新node -> left = current，返回旧的根节点
        https://leetcode.cn/problems/maximum-binary-tree-ii/solutions/1785544/by-ac_oier-v82s

         时间复杂度：O(1)
         空间复杂度：O(N)
         */
        var prev: TreeNode? = null
        var current: TreeNode? = root

        while (current != null && current.`val` > `val`) {
            // TODO:注意顺序
            prev = current
            current = current.right
        }


        val node: TreeNode = TreeNode(`val`)
        if (prev == null) {
            // val 是 最大值，将作为新节点返回
            node.left = root
            return node
        } else {
            // val 不是 最大值，旧root 仍然是根节点
            prev.right = node
            node.left = current
            return root
        }
    }
}